#ifndef __DNA_H__
#define __DNA_H__

#include <string>
#include <iostream>

// Compute array index of given nth nucleotide
#define NUCL_ARRAY_POS(n)	(n>>2) // Divide by 4
// Compute position [0..3] in storing char of given nth nucleotide
#define NUCL_CHAR_POS(n)	(n & 0x3) // Modulus 4
// Extract nucleotide from x
#define GET_NUCLEOTIDE(x,n)	((x & (0x3 << (n*2))) >> (n*2)) // for n in [0 .. 3] range
// Set nucleotide x into (char) y
#define SET_NUCLEOTIDE(y,x,n)	((y & ~(0x3 << (n*2))) | ((x & 0x3) << (n*2))) // for n in [0 .. 3] range

/* Structure holding a DNA text sequence in a compact format */
typedef struct {
    unsigned int flag:1;
    unsigned int len:7;
    char nucl[31]; // 124 letters
}DnaSeq;

/* Class used to convert nucleotide to compact format and back to letter */
class Nucl {
private:
	int l;
	Nucl(); // Made private to prevent from using default constructor
public:
	Nucl(int i) {
		if ( i<0 || i>3) throw 2; // Invalid input integer
		l=i;
	};
	Nucl(char c) {
		switch (c) {
		case 'A':
		case 'a':
			l=0;
			break;
		case 'C':
		case 'c':
			l=1;
			break;
		case 'G':
		case 'g':
			l=2;
			break;
		case 'T':
		case 't':
			l=3;
			break;
		default:
			throw 3; // Invalid input character
		}
	};
	operator int() {return l;}
	operator char() {
		switch (l) {
		case 0:
			return 'A';
			break;
		case 1:
			return 'C';
			break;
		case 2:
			return 'G';
			break;
		case 3:
			return 'T';
			break;
		default:
			throw 1; // Unexpected
		}
	};
};

std::string& conv2string (DnaSeq seq, std::string& str);

void fillDnaSeq(DnaSeq * seq, unsigned int f, unsigned int l, char * tab);
std::ostream& operator<<(std::ostream& out, DnaSeq * seq);

#endif // __DNA_H__
